<?php

namespace app\admin\controller;

use app\admin\model\Config;
use app\admin\model\Houses as HousesModel;
use app\admin\model\User;
use app\common\controller\Backend;
use app\common\library\xmwechat\offiaccount\OaService;
use app\common\model\Category;
use app\common\model\imchat\Message;
use app\common\model\Tags;
use app\common\model\Wxinfo;
use ba\Exception;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use think\facade\App;
use think\facade\Db;

/**
 * 房源管理
 */
class Houses extends Backend
{
    /**
     * Houses模型对象
     * @var object
     * @phpstan-var \app\admin\model\Houses
     */
    protected object $model;

    protected string|array $defaultSortField = 'reward,desc';

    protected array|string $preExcludeFields = ['id', 'create_time'];

    protected array $withJoinTable = ['user'];

    protected string|array $quickSearchField = ['id'];

    public function initialize(): void
    {
        parent::initialize();
        $this->model = new \app\admin\model\Houses;
    }

    /**
     * 查看
     * @throws Throwable
     */
    public function index(): void
    {

        // 如果是 select 则转发到 select 方法，若未重写该方法，其实还是继续执行 index
        if ($this->request->param('select')) {
            $this->select();
        }

        /**
         * 1. withJoin 不可使用 alias 方法设置表别名，别名将自动使用关联模型名称（小写下划线命名规则）
         * 2. 以下的别名设置了主表别名，同时便于拼接查询参数等
         * 3. paginate 数据集可使用链式操作 each(function($item, $key) {}) 遍历处理
         */
        list($where, $alias, $limit, $order) = $this->queryBuilder();
        $order['weigh'] = 'desc';
        //if (empty($order)) {
        //weigh desc,reward desc
        $order = 'weigh desc,reward desc';
        //}
        $res = $this->model
            ->withJoin($this->withJoinTable, $this->withJoinType)
            ->alias($alias)
            ->where($where)
            ->order($order)
            ->paginate($limit);
        $res->visible(['user' => ['username', 'nickname', 'mobile']]);

        $this->success('', [
            '$order' => $order,
            'list' => $res->items(),
            'total' => $res->total(),
            'remark' => get_route_remark(),
        ]);
    }


    /**
     * 添加
     */
    public function add(): void
    {
        file_put_contents('test.txt', json_encode($this->request->param(), 256));
        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (!$data) {
                $this->error(__('Parameter %s can not be empty', ['']));
            }

            $data = $this->excludeFields($data);
            if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                $data[$this->dataLimitField] = $this->auth->id;
            }

            $result = false;
            $this->model->startTrans();
            try {
                $filed_config = (new Config())->where(['id' => 17])->find();
                $checked_fields = json_decode($filed_config['value'], true);
                $checked_fields = $checked_fields ? $checked_fields : [];
                $rules = ['user_id' => 'require'];
                foreach ($checked_fields as $k => $v) {
                    $rules[$v] = 'require';
                }
                if (isset($data['status'])) {
                    $rules = ['status' => 'require'];
                }
                $validate = \think\facade\Validate::rule($rules, [
                    'name' => '房源公告标题',
                    'category_ids' => '房源类型',
                    'city' => '城市选择',
                    'introduction' => '介绍',
                    'address' => '详情地址',
                    'acreage' => '面积',
                    'rent_money' => '租金',
                    'user_id' => '发布人',
                    'has_bounty' => '是否悬赏',
                    'reward' => '悬赏金额',
                    'weigh' => '权重',
                    'image' => '主图（列表）',
                    'images' => '图册',
                    'files' => '视频',
                    'status' => '状态',
                    'rent_free' => '免租期月',
                    'start_rent' => '起租 几个月',
                    'paymethod' => '支付方式',
                    'longitude' => '经度',
                    'latitude' => '纬度',
                    'industry' => '行业',
                    'surround' => '周边配套',
                    'property' => '物业',
                    'seal_status' => '出售状态',
                    'other_tags' => '其它标签',
                    'rent_unit' => '租金单位',
                    'seach_area' => '地区最后一个id',
                    'online_time' => '上架时间',
                    'down_time' => '下架时间',
                    'prorease_period' => '预租期',
                ]);
                if (!$validate->check($data)) {
                    $this->error($validate->getError());
                }
                $result = $this->model->save($data);
                $this->model->commit();
            } catch (Throwable $e) {
                $this->model->rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success(__('Added successfully'));
            } else {
                $this->error(__('No rows were added'));
            }
        }

        $this->error(__('Parameter error'));
    }

    /**
     * 编辑
     * @throws Throwable
     */
    public function edit(): void
    {
        $pk = $this->model->getPk();
        $id = $this->request->param($pk);
        $row = $this->model->find($id);
        if (!$row) {
            $this->error(__('Record not found'));
        }

        $dataLimitAdminIds = $this->getDataLimitAdminIds();
        if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
            $this->error(__('You have no permission'));
        }

        if ($this->request->isPost()) {
            $data = $this->request->post();
            if (!$data) {
                $this->error(__('Parameter %s can not be empty', ['']));
            }

            $data = $this->excludeFields($data);
            $result = false;
            $this->model->startTrans();
            try {
                $filed_config = (new Config())->where(['id' => 17])->find();
                $checked_fields = json_decode($filed_config['value'], true);
                $checked_fields = $checked_fields ? $checked_fields : [];
                $rules = ['user_id' => 'require'];
                foreach ($checked_fields as $k => $v) {
                    $rules[$v] = 'require';
                }
                if (isset($data['status'])) {
                    $rules = ['status' => 'require'];
                }
                $validate = \think\facade\Validate::rule($rules, [
                    'name' => '房源公告标题',
                    'category_ids' => '房源类型',
                    'city' => '城市选择',
                    'introduction' => '介绍',
                    'address' => '详情地址',
                    'acreage' => '面积',
                    'rent_money' => '租金',
                    'user_id' => '发布人',
                    'has_bounty' => '是否悬赏',
                    'reward' => '悬赏金额',
                    'weigh' => '权重',
                    'image' => '主图（列表）',
                    'images' => '图册',
                    'files' => '视频',
                    'status' => '状态',
                    'rent_free' => '免租期月',
                    'start_rent' => '起租 几个月',
                    'paymethod' => '支付方式',
                    'longitude' => '经度',
                    'latitude' => '纬度',
                    'industry' => '行业',
                    'surround' => '周边配套',
                    'property' => '物业',
                    'seal_status' => '出售状态',
                    'other_tags' => '其它标签',
                    'rent_unit' => '租金单位',
                    'seach_area' => '地区最后一个id',
                    'online_time' => '上架时间',
                    'down_time' => '下架时间',
                    'prorease_period' => '预租期',
                ]);
                if (!$validate->check($data)) {
                    $this->error($validate->getError());
                }
                $result = $row->save($data);
                $this->model->commit();
            } catch (Throwable $e) {
                $this->model->rollback();
                $this->error($e->getMessage());
            }
            if ($result !== false) {
                $this->success(__('Update successful'));
            } else {
                $this->error(__('No rows updated'));
            }
        }

        $this->success('', [
            'row' => $row
        ]);
    }

    public function check()
    {
        $id = $this->request->param('id');
        $house = $this->model->find($id);
        $status = $this->request->param('status/d');
        if (!$house) {
            $this->error('房源不存在');
        }
        $wxstatus = '';
        //状态:0=下架,1=上架, 2 => '待审核', 3 => '已驳回'
        if ($status == 3) {
            $check = $this->request->param('check');
            if (empty($check)) {
                $this->error('请输入');
            }
            $wxstatus = '已驳回';
            $mark_arr = $house->mark ? json_decode($house->mark, true) : [];
            $mark_arr[] = ['admin_id' => $this->auth->id, 'check_time' => time(), 'check_mark' => $check];
            $house->check = json_encode($mark_arr, 256);
            $check = '您上传房源已被驳回，驳回原因：' . $check . '。请前往“我的发布”中查看';
            $ret = Message::insertMsg(['content' => $check, 'type' => 0, 'to_uid' => $house->user_id, 'from_uid' => 10], 10);
        } else if ($status == 1) {
            $wxstatus = '已上架';
            $check = '您上传房源已上架成功，请前往“我的发布”中查看';
            $ret = Message::insertMsg(['content' => $check, 'type' => 0, 'to_uid' => $house->user_id, 'from_uid' => 10], 10);
        } else if ($status == 0) {
            $wxstatus = '已下架';
            $check = '您上传房源已被下架，请前往“我的发布”中查看';
            $ret = Message::insertMsg(['content' => $check, 'type' => 0, 'to_uid' => $house->user_id, 'from_uid' => 10], 10);
        }
        $house->status = $status;
        $house->save();
        try {
            $unionid = (new User())->where('id', '=', $house['user_id'])->value('weixin_unionid');
            $openid = (new Wxinfo())->where(['unionid' => $unionid])->value('wxopenid');// 'oyMrVspaMfT-QfD0qjaU7W-_1tBU';
            if ($openid) {
                $template_id = 'Vhi6C97q3Y_APo6Z_jBrBngOtCoE2mq5xIvnBqniqSQ';
                $data = [
                    'const2' => ['value' => $wxstatus, 'color' => '#888888'],
                    'thing6' => ['value' => $house['name'], 'color' => '#888888'],
                    'time11' => ['value' => date('Y-m-d H:i'), 'color' => '#888888'],
                    'character_string1' => ['value' => time() . rand(999999, 1000000), 'color' => '#888888'],
                ];
                // 模板跳转链接,不跳转可忽略此参数
                $url = '';
                // 跳小程序所需数据,不需跳小程序可不用传该数据，小程序appid必须已绑定关联当前公众号
                $miniprogram = [
                    'appid' => 'wx2b1b3222bf4cab2b',
                    'pagepath' => 'pages/home/index'
                ];
                (new OaService())->sendTemplateMessage($openid, $template_id, $data, $url, $miniprogram);
            }
        } catch (Exception $exception) {

        }
        $this->success('审核成功');
    }

    /**
     * 若需重写查看、编辑、删除等方法，请复制 @see \app\admin\library\traits\Backend 中对应的方法至此进行重写
     */
    #[
        Apidoc\Title("导入房源 TODO"),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/import"),
        Apidoc\Param(name: "file", type: "string", require: true, desc: "上传文件路径", mock: "/templates/houses_template.xlsx"),
        Apidoc\Returned("id", type: "int", desc: "Id"),
    ]
    public function import(): void
    {
        set_time_limit(0);
        ob_clean();
        $file = $this->request->param('file');
        if (empty($file)) {
            $this->error('请选择上传的文件', $this->request->param());
        }
        $ext = pathinfo($file, PATHINFO_EXTENSION);//后缀
        if (!in_array($ext, ['xls', 'xlsx'])) {
            $this->error('不支持此类型文件');
        }
        if ($ext === 'xls') {
            $reader = new Xls();
        } else {
            $reader = new Xlsx();
        }
        $filePath = App::getRootPath() . 'public/' . $file;
        $data = [];
        $user_id = $this->request->param('user_id');
        $reader->setReadDataOnly(TRUE);
        $spreadsheet = $reader->load($filePath);
        $sheet = $spreadsheet->getActiveSheet();
        $highestRow = $sheet->getHighestRow();
        $allColumn = $sheet->getHighestDataColumn(); //取得最大的列号
        $allRow = $sheet->getHighestRow(); //取得一共有多少行
        $highestColumnIndex = Coordinate::columnIndexFromString($allColumn);//最大列转换成数字
        $fileds = [
            'id',
            //'name',
            'category_ids',
            'industry_pid',
            'industry',
            'city',
            'address',
            'introduction',
            'acreage',
            'rent_money',
            'has_bounty',
            'reward',
            'image',
            'images',


            //'rent_free',
//            'start_rent',
//            'paymethod',
//
//            'surround',
//            'property',
        ];
        $model = new  HousesModel();
        $field_count = count($fileds);
        for ($row = 2; $row <= $highestRow; $row++) {
            // 构建默认字段数据
            $arr_value = [
                'create_time' => time(),
                'update_time' => time(),
            ];
            // 列，行
            $value = $sheet->getCell('A' . $row)->getValue();
            if (!empty($value)) {
                for ($col = 1; $col <= $field_count - 1; $col++) {
                    // 'A' 对应的ASCII码十进制为 64
                    // 将ASCII值转为字符
                    $chr = $this->getColumnZimu($col);
                    // 列转为数据库字段名
                    $key = $fileds[$col] ?? $chr;
                    $value = $sheet->getCell($chr . $row)->getValue();
                    if (in_array($key, ['image', 'images']) && !empty($value)) {
                        $value = '';
                    }
                    if ($key == 'category_ids' && !empty($value)) {
                        $value = (new Category())->where('name', $value)->value('id');
                    }
                    if (in_array($key, ['industry_pid', 'industry', 'surround', 'property']) && !empty($value)) {
                        $speal_arr = array('；', ';');
                        foreach ($speal_arr as $speal) {
                            $value = str_replace($speal, ',', $value);
                        }
                        $cate_values = explode(',', $value);
                        $cate_ids = (new Tags())->whereIn('string', $cate_values)->column('id');
                        $value = $cate_ids ? implode(',', $cate_ids) : '';
                    }
                    if ($key == 'city') {
                        $value = str_replace(',', ',', $value);
                        $value = str_replace('，', ',', $value);
                        $value = str_replace('；', ',', $value);
                        $value = str_replace(';', ',', $value);
                        $value = Db::name('area')->whereIn('name', $value)->column('id');
                        $value = $value ? implode(',', $value) : '';
                    }
                    $value = trim($value);
                    // 构建当前行数据
                    $arr_value[$key] = $value;
                }
                $arr_value['user_id'] = $user_id;
                $arr_value['status'] = 0;
                $arr_value['source'] = 1;
                $arr_value['name'] = '导入房源11';
                $data[] = $arr_value;
            }
        }
        $imageFilePath = App::getRootPath() . 'public/uploads/imgs'; //图片本地存储的路径
        $objRead = IOFactory::createReader('Xlsx');
        $objSpreadsheet = $objRead->load($filePath);
        $objWorksheet = $objSpreadsheet->getSheet(0);
        $images_datas = [];
        $images = [];
        foreach ($objWorksheet->getDrawingCollection() as $drawing) {
            $chr = $this->getColumnZimu(0);

            list($startColumn, $startRow) = Coordinate::coordinateFromString($drawing->getCoordinates());
            $imageFileName = $drawing->getCoordinates() . mt_rand(1000, 9999);
            switch ($drawing->getExtension()) {
                case 'jpg':
                case 'jpeg':
                    $imageFileName .= '.jpg';
                    $source = imagecreatefromjpeg($drawing->getPath());
                    imagejpeg($source, $imageFilePath . $imageFileName);
                    break;
                case 'gif':
                    $imageFileName .= '.gif';
                    $source = imagecreatefromgif($drawing->getPath());
                    imagegif($source, $imageFilePath . $imageFileName);
                    break;
                case 'png':
                    $imageFileName .= '.png';
                    $source = imagecreatefrompng($drawing->getPath());
                    imagepng($source, $imageFilePath . $imageFileName);
                    break;
            }
            $startColumn = $this->ABC2decimal($startColumn);
            // 列，行
            $value = $sheet->getCell($chr . $startRow)->getValue();
            if (!empty($value)) {


                if ($startColumn == 11) {
                    $data[$startRow - 2]['image'] = ',' . '/uploads/imgs' . $imageFileName;
                }
                if ($startColumn == 12) {
                    $data[$startRow - 2]['images'] = ',' . '/uploads/imgs' . $imageFileName;
                }
            }

        }
        $result = $model->saveAll($data);
        if ($result) {
            $this->success('导入成功' . count($data) . '条数据', $data);
        } else {
            $this->error('导入失败', $data);
        }
    }

    private function getColumnZimu($num)
    {
        if ($num >= 0 && $num < 26) {
            // 如果是 A 到 Z 之间的列，直接返回对应的字母
            return chr(65 + $num);
        } else {
            // 针对 AA、AB、AC ... ZZ 这样的列，使用类似递归的方式计算出对应的字母组合
            $result = '';
            while ($num >= 26) {
                $result .= chr(65 + ($num % 26));
                $num = intval($num / 26) - 1;
            }
            $result .= chr(65 + $num);
            return strrev($result); // 需要反转列名字母组合
        }
    }

    public function ABC2decimal($abc)
    {
        $ten = 0;
        $len = strlen($abc);
        for ($i = 1; $i <= $len; $i++) {
            $char = substr($abc, 0 - $i, 1);//反向获取单个字符
            $int = ord($char);
            $ten += ($int - 65) * pow(26, $i - 1);
        }
        return $ten;
    }

    public function customFieldsSave()
    {
        if ($this->request->isPost()) {

            $filed_config = (new Config())->where(['id' => 17])->find();
            $custom_fields = json_encode($this->request->post('custom_fields'), 256);
            $filed_config->save([
                'value' => $custom_fields
            ]);
            $this->success('提交成功', $this->request->param());
        }
        $custom_fields = [
            ['field' => 'category_ids', 'name' => '房源类型']
            , ['field' => 'industry', 'name' => '行业']
            , ['field' => 'acreage', 'name' => '面积']
            , ['field' => 'rent_money', 'name' => '租金']
            , ['field' => 'city', 'name' => '城市选择'],
            ['field' => 'address', 'name' => '详情地址']
            , ['field' => 'image', 'name' => '主图（列表）']
            , ['field' => 'images', 'name' => '图册']
            //,['field' => 'name', 'name' => '房源公告标题']
            , ['field' => 'introduction', 'name' => '房源详情']
            # , ['field' => 'has_bounty', 'name' => '是否悬赏']
            , ['field' => 'reward', 'name' => '悬赏金额']
            , ['field' => 'user_id', 'name' => '发布人']
//            , ['field' => 'files', 'name' => '视频']
//            , ['field' => 'rent_free', 'name' => '免租期']
//            , ['field' => 'start_rent', 'name' => '起租 几个月']
//            , ['field' => 'paymethod', 'name' => '支付方式']

//            , ['field' => 'surround', 'name' => '周边配套']
//            , ['field' => 'property', 'name' => '物业']
//            , ['field' => 'other_tags', 'name' => '其它标签']
//            , ['field' => 'rent_unit', 'name' => '租金单位']
//            , ['field' => 'online_time', 'name' => '上架时间']
//            , ['field' => 'down_time', 'name' => '下架时间']
            //, ['field' => 'prorease_period', 'name' => '预租期']
        ];
        $filed_config = (new Config())->where(['id' => 17])->find();
        $checked_fields = json_decode($filed_config['value'], true);
        $checked_fields = $checked_fields ? $checked_fields : [];
        $this->success('自定义配置字段', ['custom_fields' => $custom_fields, 'checked_fields' => $checked_fields]);
    }

    public function batchPass()
    {
        $ids = $this->request->post('ids/a');
        $houses = HousesModel::where('id', 'in', $ids)
            ->where('status', '<>', 1)
            ->select();
        if (empty($houses)) {
            $this->error('房源不存在');
        }

        $data = [];
        foreach ($houses as $house) {
            $data[] = [
                'id' => $house['id'],
                'status' => 1,
            ];
            $check = '您上传房源已上架成功，请前往“我的发布”中查看';
            $ret = Message::insertMsg(['content' => $check, 'type' => 0, 'to_uid' => $house->user_id, 'from_uid' => 10], 10);
        }
        $result = (new HousesModel())->saveAll($data);
        if ($result) {
            $this->success('批量通过成功');
        } else {
            $this->error('批量通过失败');
        }

    }
}
